package com.yqw.onlineDocs.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yqw.onlineDocs.common.ErrorCode;
import com.yqw.onlineDocs.exception.BusinessException;
import com.yqw.onlineDocs.exception.ThrowUtils;
import com.yqw.onlineDocs.mapper.DocumentUserMapper;
import com.yqw.onlineDocs.model.dto.documentUser.DocumentUserAddRequest;
import com.yqw.onlineDocs.model.dto.documentUser.DocumentUserQueryRequest;
import com.yqw.onlineDocs.model.entity.Document;
import com.yqw.onlineDocs.model.entity.DocumentUser;
import com.yqw.onlineDocs.model.entity.User;
import com.yqw.onlineDocs.model.enums.DocumentPermissionEnum;
import com.yqw.onlineDocs.model.vo.DocumentUserVO;
import com.yqw.onlineDocs.model.vo.DocumentVO;
import com.yqw.onlineDocs.model.vo.UserVO;
import com.yqw.onlineDocs.service.DocumentService;
import com.yqw.onlineDocs.service.DocumentUserService;
import com.yqw.onlineDocs.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author gemdzq
 * @description 针对表【document_user(文档用户关联)】的数据库操作Service实现
 * @createDate 2025-06-19 14:13:34
 */
@Slf4j
@Service
public class DocumentUserServiceImpl extends ServiceImpl<DocumentUserMapper, DocumentUser>
    implements DocumentUserService {

  @Resource
  private DocumentService documentService;

  @Resource
  private UserService userService;

  /**
   * 新增文档用户关联
   *
   * @param documentUserAddRequest
   * @return
   */
  @Override
  public long addDocumentUser(DocumentUserAddRequest documentUserAddRequest) {
    // 参数校验
    ThrowUtils.throwIf(documentUserAddRequest == null, ErrorCode.PARAMS_ERROR, "参数不能为空");
    DocumentUser documentUser = new DocumentUser();
    BeanUtils.copyProperties(documentUserAddRequest, documentUser);
    validateDocumentUser(documentUser, true);
    // 数据库操作
    boolean result = this.save(documentUser);
    ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "新增文档用户关联失败");
    return documentUser.getId();
  }

  /**
   * 校验文档用户关联
   *
   * @param documentUser
   * @param add
   */
  @Override
  public void validateDocumentUser(DocumentUser documentUser, boolean add) {
    // 参数校验
    ThrowUtils.throwIf(documentUser == null, ErrorCode.PARAMS_ERROR, "参数不能为空");
    Long documentId = documentUser.getDocumentId();
    Long userId = documentUser.getUserId();
    if (add) {
      ThrowUtils.throwIf(ObjUtil.hasEmpty(documentId, userId), ErrorCode.PARAMS_ERROR, "文档ID和用户ID不能为空");
      // 添加日志输出，帮助调试
      log.info("正在验证用户ID: {}", userId);
      User user = userService.getById(userId);
      log.info("查询用户结果: {}", user);
      ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR, "用户不存在");
      Document document = documentService.getById(documentId);
      ThrowUtils.throwIf(document == null, ErrorCode.NOT_FOUND_ERROR, "文档不存在");
    }
    // 校验权限
    String permission = documentUser.getPermission();
    DocumentPermissionEnum documentPermissionEnum = DocumentPermissionEnum.getEnumByValue(permission);
    if (permission != null && documentPermissionEnum == null) {
      throw new BusinessException(ErrorCode.PARAMS_ERROR, "权限值不正确");
    }
  }

  /**
   * 获取查询条件的QueryWrapper
   *
   * @param documentUserQueryRequest
   * @return
   */
  @Override
  public QueryWrapper<DocumentUser> getQueryWrapper(DocumentUserQueryRequest documentUserQueryRequest) {
    QueryWrapper<DocumentUser> queryWrapper = new QueryWrapper<>();
    if (documentUserQueryRequest == null) {
      return queryWrapper;
    }
    // 从对象中取值
    Long id = documentUserQueryRequest.getId();
    Long documentId = documentUserQueryRequest.getDocumentId();
    Long userId = documentUserQueryRequest.getUserId();
    String permission = documentUserQueryRequest.getPermission();
    queryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
    queryWrapper.eq(ObjUtil.isNotEmpty(documentId), "documentId", documentId);
    queryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
    queryWrapper.eq(ObjUtil.isNotEmpty(permission), "permission", permission);
    return queryWrapper;
  }

  /**
   * 获取文档VO
   *
   * @param documentUser
   * @param request
   * @return
   */
  @Override
  public DocumentUserVO getDocumentUserVO(DocumentUser documentUser, HttpServletRequest request) {
    // 对象类转封装类
    DocumentUserVO documentUserVO = DocumentUserVO.objToVo(documentUser);
    // 关联查询用户信息
    Long userId = documentUser.getUserId();
    if (userId != null && userId > 0) {
      User user = userService.getById(userId);
      UserVO userVO = userService.getUserVO(user);
      documentUserVO.setUser(userVO);
    }
    // 关联查询文档信息
    Long documentId = documentUser.getDocumentId();
    if (documentId != null && documentId > 0) {
      Document document = documentService.getById(documentId);
      DocumentVO documentVO = documentService.getDocumentVO(document, request);
      documentUserVO.setDocument(documentVO);
    }
    return documentUserVO;
  }

  /**
   * 获取文档用户VO列表
   *
   * @param documentUserList
   * @return
   */
  @Override
  public List<DocumentUserVO> getDocumentUserVOList(List<DocumentUser> documentUserList) {
    if (CollUtil.isEmpty(documentUserList)) {
      return Collections.emptyList();
    }
    // 对象列表 => 封装对象列表
    List<DocumentUserVO> documentUserVOList = documentUserList.stream().map(DocumentUserVO::objToVo)
        .collect(Collectors.toList());
    // 1. 收集需要关联查询的用户 ID 和文档 ID
    Set<Long> userIdSet = documentUserList.stream().map(DocumentUser::getUserId).collect(Collectors.toSet());
    Set<Long> documentIdSet = documentUserList.stream().map(DocumentUser::getDocumentId).collect(Collectors.toSet());
    // 2. 批量查询用户和文档信息
    Map<Long, List<User>> userIdUserListMap = userService.listByIds(userIdSet).stream()
        .collect(Collectors.groupingBy(User::getId));
    Map<Long, List<Document>> documentIdDocumentMap = documentService.listByIds(documentIdSet).stream()
        .collect(Collectors.groupingBy(Document::getId));
    // 3. 填充 DocumentUserVO 的用户和文档信息
    documentUserVOList.forEach(documentUserVO -> {
      Long userId = documentUserVO.getUserId();
      Long documentId = documentUserVO.getDocumentId();
      User user = null;
      if (userIdUserListMap.containsKey(userId)) {
        user = userIdUserListMap.get(userId).get(0);
      }
      documentUserVO.setUser(userService.getUserVO(user));
      Document document = null;
      if (documentIdDocumentMap.containsKey(documentId)) {
        document = documentIdDocumentMap.get(documentId).get(0);
      }
      documentUserVO.setDocument(DocumentVO.objToVo(document));
    });
    return documentUserVOList;
  }

  /**
   * 根据文档ID和用户ID获取文档用户关联
   *
   * @param documentId
   * @param userId
   * @return
   */
  @Override
  public DocumentUser getDocumentUserByDocumentIdAndUserId(Long documentId, Long userId) {
    QueryWrapper<DocumentUser> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("documentId", documentId);
    queryWrapper.eq("userId", userId);
    return this.getOne(queryWrapper);
  }

}
